/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.ui 
{
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.utils.Dictionary;

	public class KeyManager 
	{
		// ___________________________________________________________________ CONSTANTS		
		
		// ___________________________________________________________________ CLASS PROPERTIES
		
		private static var _initialized										: Boolean = false;
		private static var _keys											: Dictionary;
		private static var _up												: Dictionary;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private static var _instance	: KeyManager;
		
		// ___________________________________________________________________ GETTERS AND SETTERS
		
		// ___________________________________________________________________ CONSTRUCTOR
		
		public function KeyManager (singleton:SingletonObligate) {}
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		public static function getInstance () : KeyManager
		{
			if (!KeyManager._instance) KeyManager._instance = new KeyManager(new SingletonObligate());
			return KeyManager(KeyManager._instance);
		}
		
		public function init(stage:Stage):void
		{
			if (_initialized) return;
			_initialized = true;
			
			clearKeys(null);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			stage.addEventListener(Event.DEACTIVATE, clearKeys);
		}
		
		public function destroy(stage:Stage):void
		{
			_keys = null;
			_up = null;
			
			_initialized = false;
			
			stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			stage.removeEventListener(Event.DEACTIVATE, clearKeys);				 
		}
		
		public function isDown(keyCode:uint, releaseKey:Boolean = false):Boolean {
			if (!_initialized) return false;			
			
			if (releaseKey) {				
				if (!_up[keyCode] && _up[keyCode] != undefined)								
				return false;
			}
			
			if (_up[keyCode] != undefined && _keys[keyCode])
			_up[keyCode] = false;
			
			return _keys[keyCode];
		}
		
		
		public function isUp(keyCode:uint):Boolean {
			if (!_initialized) return false;
			
			return _up[keyCode];
		}
		
		// ___________________________________________________________________ PRIVATE METHODS
		
		// ___________________________________________________________________ EVENTS
		
		static private function onKeyDown(e:KeyboardEvent):void 
		{			
			if (!_initialized) return;			
			
			_keys[e.keyCode] = true;	
			
			if (_up[e.keyCode] == undefined)
			_up[e.keyCode] = true;
		}
		
		static private function onKeyUp(e:KeyboardEvent):void 
		{
			if (!_initialized) return;
			
			_keys[e.keyCode] = false;
			_up[e.keyCode] = true;			
		}
		
		static private function clearKeys(e:Event):void 
		{
			_keys = new Dictionary();
			_up = new Dictionary();
		}
	}
}

class SingletonObligate {}